package cn.edu.sgu.www.mhxysy.service.system.impl;

import cn.edu.sgu.www.mhxysy.entity.system.ClassProperty;
import cn.edu.sgu.www.mhxysy.entity.system.Table;
import cn.edu.sgu.www.mhxysy.feign.clients.pms.PmsFeignService;
import cn.edu.sgu.www.mhxysy.restful.JsonResult;
import cn.edu.sgu.www.mhxysy.service.system.TableService;
import cn.edu.sgu.www.mhxysy.util.StringUtils;
import cn.edu.sgu.www.mhxysy.util.TableReaderUtils;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableName;
import io.swagger.annotations.ApiModelProperty;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.lang.reflect.Field;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.*;

/**
 * @author 沐雨橙风ιε
 * @version 1.0
 */
@Service
public class TableServiceImpl implements TableService {

    /**
     * 应用名
     */
    @Value("${spring.application.name}")
    private String service;

    private final PmsFeignService feignService;

    @Autowired
    public TableServiceImpl(PmsFeignService feignService) {
        this.feignService = feignService;
    }

    /**
     * 创建一个map，保存Java数据类型和数据库字段类型的映射关系
     */
    private final Map<Class<?>, String> CLASS_STRING_MAP = new HashMap<>();

    {
        CLASS_STRING_MAP.put(Integer.class, "int(11) unsigned");
        CLASS_STRING_MAP.put(Date.class, "date");
        CLASS_STRING_MAP.put(LocalDate.class, "date");
        CLASS_STRING_MAP.put(LocalDateTime.class, "datetime");
        CLASS_STRING_MAP.put(String.class, "varchar(255)");
    }

    public String getType(Class<?> propertyType) {
        return CLASS_STRING_MAP.get(propertyType);
    }

    @Override
    public List<Table> selectAll() {
        JsonResult<List<Table>> jsonResult = feignService.selectByDatabase(service);

        if (jsonResult.isSuccess()) {
            return jsonResult.getData();
        }

        return null;
    }

    @Override
    public List<String> getTableNames() throws IOException {
        JsonResult<List<String>> jsonResult = feignService.getTableNames(service);

        if (jsonResult.isSuccess()) {
            List<String> tableNames = TableReaderUtils.getTableNames();
            List<String> list = jsonResult.getData();

            for (String tableName : tableNames) {
                if (!list.contains(tableName)) {
                    System.out.println("数据库中没有对应的表：" + tableName);
                }
            }
            for (String entity : list) {
                if (!tableNames.contains(entity)) {
                    System.out.println("实体类中没有数据库对应的表：" + entity);
                }
            }

            return list;
        }

        return null;
    }

    @Override
    public String generate(String className) throws ClassNotFoundException {
        // 获取类对象
        Class<?> type = Class.forName(className);

        // 获取表名
        String tableName;

        // Mybatis-Plus的@TableName注解设置了表名
        if (type.isAnnotationPresent(TableName.class)) {
            TableName annotation = type.getAnnotation(TableName.class);

            tableName = annotation.value();
            tableName = StringUtils.isNotEmpty(tableName) ? tableName : StringUtils.toLower(className);
        } else {
            // 没有设置表名，则将类名转为下划线命名
            tableName = StringUtils.toLower(className);
        }

        // 获取类的所有字段信息
        Field[] fields = type.getDeclaredFields();
        // 创建一个list保存所有表所有字段的信息
        List<ClassProperty> list = new ArrayList<>(fields.length);

        for (Field field : fields) {
            String fieldName = field.getName();

            // 排除序列化ID
            if (!"serialVersionUID".equals(fieldName)) {
                ClassProperty classProperty = new ClassProperty();

                // 字段名
                if (field.isAnnotationPresent(TableField.class)) {
                    TableField tableField = field.getAnnotation(TableField.class);

                    classProperty.setName(tableField.value());
                } else {
                    classProperty.setName(StringUtils.toLower(fieldName));
                }

                // 字段类型
                String fieldType = getType(field.getType());

                classProperty.setDataType(fieldType);

                // 字段注释
                if (field.isAnnotationPresent(ApiModelProperty.class)) {
                    ApiModelProperty apiModelProperty = field.getAnnotation(ApiModelProperty.class);

                    classProperty.setComment(apiModelProperty.value());
                    classProperty.setNotNull(apiModelProperty.required());
                }

                list.add(classProperty);
            }
        }

        // 开始拼接SQL语句
        StringBuilder sb = new StringBuilder();

        sb.append("create table `").append(tableName).append("` (");

        for (ClassProperty classProperty : list) {
            sb.append("`").append(classProperty.getName()).append("` ");
            sb.append(classProperty.getDataType()).append(" ");

            if (classProperty.isNotNull()) {
                sb.append("not null ");
            }

            if ("id".equals(classProperty.getName())) {
                sb.append("primary key ");

                if (classProperty.getDataType().contains("int")) {
                    sb.append("auto_increment ");
                }
            }

            sb.append("comment '").append(classProperty.getComment()).append("', ");
        }

        return sb.substring(0, sb.length() - 2) + ");";
    }

}